package com.luoxue.execsql.rest.service.impl;

import com.luoxue.execsql.rest.bean.base.service.impl.BaseServiceImpl;
import com.luoxue.execsql.rest.entity.CommonValidator;
import com.luoxue.execsql.rest.entity.DynamicSql;
import com.luoxue.execsql.rest.entity.ErrorValidator;
import com.luoxue.execsql.rest.entity.ParameterValidation;
import com.luoxue.execsql.rest.mapper.CommonValidatorMapper;
import com.luoxue.execsql.rest.mapper.ParameterValidationMapper;
import com.luoxue.execsql.common.util.MyStringUtil;
import com.luoxue.execsql.rest.service.IParameterValidationService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Pattern;

@Service
public class ParameterValidationService extends BaseServiceImpl<ParameterValidation, ParameterValidationMapper> implements IParameterValidationService {

    @Resource
    CommonValidatorMapper commonValidatorMapper;

    public ParameterValidationService(ParameterValidationMapper mapper) {
        super(mapper);
    }


    public List<ErrorValidator> parameterValidate(String sqlTag, Map<String, Object> paramMap) {
        List<ErrorValidator> validationMsgList = new ArrayList<>();
        List<ParameterValidation> parameterValidationList = mapper.selectBySqlTag(sqlTag);
        if (parameterValidationList != null && !parameterValidationList.isEmpty()) {
            Set<String> regexTypes = new HashSet<>();
            parameterValidationList.forEach(parameterValidation -> {
                String regexType = parameterValidation.getRegexType();
                if (!isCustomRegexType(regexType)) {
                    regexTypes.add(parameterValidation.getRegexType());
                }
            });
            List<CommonValidator> commonValidatorList = commonValidatorMapper.selectByRegexTypes(regexTypes);
            parameterValidationList.forEach(validator -> {
                String paramName = validator.getParamName();
                Object paramValueO = paramMap.get(paramName);
                if (paramValueO == null) {
                    validationMsgList.add(new ErrorValidator(paramName, null, "参数为空"));
                    return;
                }
                String paramValue = String.valueOf(paramValueO);

                String regexType = validator.getRegexType();
                ErrorValidator validatorMsg = null;
                if (isCustomRegexType(regexType)) {
                    if (!Pattern.matches(validator.getRegexText(), paramValue)) {
                        validatorMsg = new ErrorValidator(paramName, regexType, MyStringUtil.getValue(validator.getErrorMsg()));
                    }
                } else {
                    Optional<CommonValidator> optional = commonValidatorList.stream().filter(cValidator -> cValidator.getRegexType().equals(regexType)).findFirst();
                    if (optional.isPresent()) {
                        CommonValidator commonValidator = optional.get();
                        if (!Pattern.matches(commonValidator.getRegexText(), paramValue)) {
                            validatorMsg = new ErrorValidator(paramName, regexType, MyStringUtil.getValue(MyStringUtil.getValue(commonValidator.getErrorMsg(), validator.getErrorMsg())));
                        }
                    } else {
                        validatorMsg = new ErrorValidator(paramName, regexType, "未匹配到校验规则");
                    }
                }
                if (validatorMsg != null) {
                    validationMsgList.add(validatorMsg);
                }
            });
        }

        return validationMsgList;
    }


    private Boolean isCustomRegexType(String regexType) {
        return Strings.isBlank(regexType) || regexType.equals("custom");
    }

    public void saveByDynamicSql(DynamicSql entity) {
        String sqlTag = entity.getSqlTag();
        mapper.deleteBySqlTag(sqlTag);
        List<ParameterValidation> parameterValidationList = entity.getParameterValidationList();
        if (!CollectionUtils.isEmpty(parameterValidationList)) {
            parameterValidationList.forEach(parameterValidation -> {
                parameterValidation.setSqlTag(sqlTag);
                this.save(parameterValidation);
            });
        }
    }

    public List<ParameterValidation> selectBySqlTag(String sqlTag) {
        return mapper.selectBySqlTag(sqlTag);
    }
}
